package ui;

import java.awt.event.MouseEvent;

import org.apache.log4j.Logger;

import animations.MyBall;

import utility.AppUtilities;

public class WorkModel implements MyModelIfc {
	private static final Logger LOGGER = Logger.getLogger(WorkModel.class);
	protected MouseEvent mouseEvent;
	protected final AppUtilities utilities;

	private double counter;
	// The velocity is plus up acceleration per time unit 9.8 * 10^(-3) mm/s^2
	public final double ACCELERATION = 0.0098;
	public final double PIXEL = 10; // conversion ratio: 1 pixel = PIXEL millimeter(s)
	private double x; // Abscissa = x
	private double y; // Height = y
	private double xOld;
	private double yOld;
	private double vInit;
	private int direction;
	private double yMax;
	private double diameter;
	private double loseEnergy;
	private MyBall myBall;

	public WorkModel() {
		this.utilities = AppUtilities.createAppUtilities();
		this.xOld = -1;
		this.yOld = -1;

		try {
			utilities.put(getClass().getName(), this);
		}catch (Exception e) {
			LOGGER.warn(e.getMessage(), e.getCause());
		}
	}

	/**
	 * @return the mouseEvent
	 */
	public MouseEvent getMouseEvent() {
		return mouseEvent;
	}

	/**
	 * @param mouseEvent
	 *            the mouseEvent to set
	 */
	public void setMouseEvent(MouseEvent mouseEvent) {
		this.mouseEvent = mouseEvent;
		this.counter = 0;
		this.x = mouseEvent.getX();
		this.y = mouseEvent.getY();
		this.yOld = this.y;
		this.vInit = 0;
		this.direction = 1;
		this.yMax = 510;
		this.diameter = 50;
		this.loseEnergy = 0.05;
	}

	/**
	 * This function is invoked automatically
	 * 
	 * @param deltaT
	 */
	public void countUp(double deltaT) {
		double dT = Math.abs(deltaT) / 1000000L;
		counter += dT;
		excuteOperation(dT);
	}

	public int getX() {
		return (int) Math.ceil(x);
	}

	public int getY() {
		return (int) Math.ceil(y);
	}

	public int getxOld() {
		return (int) Math.ceil(xOld);
	}

	/**
	 * @return the yOld
	 */
	public double getyOld() {
		return yOld;
	}

	public double getCounter() {
		return counter / 1000;
	}

	private void excuteOperation(double deltaT) {
		if(direction == 0) {
			return;
		}

		double deltaV = ACCELERATION * deltaT;
		double deltaY = (vInit * deltaT + 0.5 * ACCELERATION * Math.pow(deltaT, 2)) / PIXEL;

		vInit += deltaV * direction;
		y += deltaY * direction;

		if((y + diameter) > yMax) {
			direction = -1;
			if(vInit > loseEnergy) {
				vInit -= loseEnergy;
			}
			else {
				direction = 0;
			}
		}

		if(vInit < 0) {
			direction = 1;
		}

		myBall.setX(getX());
		myBall.setY(getY());
	}

	public void setMyBall(MyBall myBall) {
		this.myBall = myBall;
		this.x = myBall.getX();
		this.y = myBall.getY();

		this.yOld = this.y;
		this.vInit = 0;
		this.direction = 1;
		this.yMax = 510;
		this.diameter = 50;
		this.loseEnergy = 0.05;
	}
}
